// auth.service.ts
import { Injectable, Inject } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { UserService } from '../user/user.service';
import { LogService } from '../log/log.service';
import { User } from '../user/entities/user.entity';
import * as Redis from 'ioredis';

@Injectable()
export class AuthService {
  private readonly MAX_LOGIN_ATTEMPTS = 3;
  private readonly LOCK_TIME = 60 * 1000;
  private readonly redisClient: Redis.Redis;

  constructor(
    private readonly jwtService: JwtService,
    private readonly userService: UserService,
    private readonly logService: LogService,
    @Inject('REDIS_CLIENT') redisClient: Redis.Redis,
  ) {
    this.redisClient = redisClient;
  }

  async login(username: string, password: string): Promise<string> {
    const cacheKey = `user:${username}`;
    const cachedUser = await this.redisClient.get(cacheKey);
    let user: User;

    if (cachedUser) {
      user = JSON.parse(cachedUser);
    } else {
      user = await this.userService.findByUsername(username);
      if (!user) {
        throw new Error('User not found');
      }
      await this.redisClient.set(cacheKey, JSON.stringify(user), 'EX', 60);
    }

    if (user.lockedUntil && user.lockedUntil > new Date()) {
      throw new Error('Account locked');
    }

    if (await user.comparePassword(password)) {
      user.loginAttempts = 0;
      await user.save();
      const payload = { username };
      const token = this.jwtService.sign(payload);
      await this.logService.logLogin(user);
      return token;
    } else {
      user.loginAttempts++;
      if (user.loginAttempts >= this.MAX_LOGIN_ATTEMPTS) {
        user.lockedUntil = new Date(Date.now() + this.LOCK_TIME);
        await user.save();
        throw new Error('Account locked');
      } else {
        await user.save();
        throw new Error('Invalid password');
      }
    }
  }
}
